<HTML>
	<HEAD>
		<TITLE>6502 Algorithms</TITLE>
		<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
		<LINK REL="StyleSheet" HREF="../obelisk.css" TYPE="text/css" media="screen,print">
	</HEAD>
	<BODY>
<script type="text/javascript"><!--
google_ad_client = "pub-0826595092783671";
/* 6502 Header */
google_ad_slot = "9208748029";
google_ad_width = 728;
google_ad_height = 90;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
<HR>
		<H2><STRONG>Coding Algorithms</STRONG></H2>
		<P>As you can see from the preceding descriptions the instruction set of the 6502
			is quite basic, having only simple 8 bit operations. Complex operations such as
			16 or 32 bit arithmetic and memory transfers have to be performed by executing
			a sequence of simpler operations. This sections describes how to build these
			algorithms and is based on code taken from my macro library (available from the <A href="downloads.html#source">
				download section</A>).</P>
		<P>If you find any bugs in the code, have routines to donate to the library, or can
			suggest improvements then please mail me.</P>
		<H3>Standard Conventions</H3>
		<P>The 6502 processor expects addresses to be stored in 'little endian' order, with
			the least significant byte first and the most significant byte second. If the
			value stored was just a number (e.g. game score, etc.) then we could write code
			to store and manipulate it in 'big endian' order if we wished, however the
			algorithms presented here always use 'little endian' order so that they may be
			applied either to simple numeric values or addresses without
        modification.</P>
        <dl>
          <dd><p><i>The terms 'big endian' and 'little endian' come from Gulliver's
        Travels. The people of Lilliput and Blefuscu have been fighting a war
        over which end of an boiled egg one should crack to eat it. In computer terms it refers to whether the most or least significant&nbsp;
        portion of a binary number is stored in the lower memory address.</i></p>
          </dd>
        </dl>
		<P>To be safe the algorithms usually start by setting processor flags and registers
			to safe initial values. If you need to squeeze a few extra bytes or cycles out
			of the routine you might be able to remove some of these initializations
			depending on the preceding instructions.</P>
		<H3>Simple Memory Operations</H3>
		<P>Probably the most fundamental memory operation is clearing an area of memory to
			an initial value, such as zero. As the 6502 cannot directly move values to
			memory clearing even a small region of memory requires the use of a register.
			Any of A, X or Y could be used to hold the initial value, but in practice A is
			normally used because it can be quickly saved and restored (with PHA and PLA)
			leaving X and Y free for application use.</P>
		<PRE>; Clearing 16 bits of memory
_CLR16  LDA #0          ;Load constant zero into A
        STA MEM+0       ;Then clear the least significant byte
        STA MEM+1       ;... followed by the most significant

; Clearing 32 bits of memory
_CLR32  LDA #0          ;Load constant zero into A
        STA MEM+0       ;Clear from the least significant byte
        STA MEM+1       ;... up
        STA MEM+2       ;... to
        STA MEM+3       ;... the most significant</PRE>
		<P>Moving a small quantity of data requires a register to act as a temporary
			container during the transfer. Again any of A, X, or Y may be used, but as
			before using A as the temporary register is often the most practical.</P>
		<PRE>; Moving 16 bits of memory
_XFR16  LDA SRC+0       ;Move the least significant byte
        STA DST+0
        LDA SRC+1       ;Then the most significant
        STA DST+1

; Moving 32 bits of memory
_XFR32  LDA SRC+0       ;Move from least significant byte
        STA DST+0
        LDA SRC+1       ;... up
        STA DST+1
        LDA SRC+2       ;... to
        STA DST+2
        LDA SRC+3       ;... the most significant
        STA DST+3</PRE>
		<P>Provided the source and destination areas do not overlap then the order in which
			the bytes are moved is irrelevant, but it usually pays to be consistent in your
			approach to make mistakes easier to spot.</P>
		<P>All of the preceding examples can be extended to apply to larger memory areas
			but will generate increasingly larger code as the number of bytes involved
			grows. Algorithms that iterate using a counter and use index addressing to
			access memory will result in smaller code but will be slightly slower to
			execute.</P>
		<P>This trade off between speed and size is a common issue in assembly language
			programming and there are times when one approach is clearly better than the
			other (e.g. when trying to squeeze code into a fixed size ROM - SIZE, or
			manipulate data during a video blanking period - SPEED).</P>
		<PRE>; Clear 32 bits of memory iteratively
_CLR32C LDX #3
        LDA #0
_LOOP   STA MEM,X
        DEX
        BPL _LOOP

; Move 32 bits of memory iteratively
_XFR32C LDX #3
_LOOP   LDA SRC,X
        STA DST,X
        DEX
        BPL _LOOP</PRE>
		<P>Another basic operation is setting a 16 bit word to an initial constant value.
			The easiest way to do this is to load the low and high portions into A one at a
			time and store them.</P>
		<PRE>; Setting a 16 bit constant
_SET16I LDA #LO NUM     ;Set the least significant byte of the constant
        STA MEM+0
        LDA #HI NUM     ;... then the most significant byte
        STA MEM+1</PRE>
		<h3>Logical Operations</h3>
		<p>The simplest forms of operation on binary values are the logical AND, logical OR
			and exclusive OR illustrated by the following truth tables.&nbsp;</p>
		<table width="100%" border="0">
			<tbody>
				<tr>
					<td width="20%"><b><i>Logical AND (AND)</i></b></td>
					<td width="10%"></td>
					<td width="20%"><b><i>Logical OR (ORA)</i></b></td>
					<td width="10%"></td>
					<td width="20%"><b><i>Exclusive OR (EOR)</i></b></td>
				</tr>
				<tr>
					<td width="20%">
						<table width="100%" border="0">
							<tbody>
								<tr>
									<td width="33%"></td>
									<td width="33%" bgColor="#000000"><font color="#ffffff">0</font></td>
									<td width="34%" bgColor="#000000"><font color="#ffffff">1</font></td>
								</tr>
								<tr>
									<td width="33%" bgColor="#000000"><font color="#ffffff">0</font></td>
									<td width="33%" bgColor="#c0c0c0">0</td>
									<td width="34%" bgColor="#c0c0c0">0</td>
								</tr>
								<tr>
									<td width="33%" bgColor="#000000"><font color="#ffffff">1</font></td>
									<td width="33%" bgColor="#c0c0c0">0</td>
									<td width="34%" bgColor="#c0c0c0">1</td>
								</tr>
							</tbody>
						</table>
					</td>
					<td width="10%"></td>
					<td width="20%">
						<table width="100%" border="0">
							<tbody>
								<tr>
									<td width="33%"></td>
									<td width="33%" bgColor="#000000"><font color="#ffffff">0</font></td>
									<td width="34%" bgColor="#000000"><font color="#ffffff">1</font></td>
								</tr>
								<tr>
									<td width="33%" bgColor="#000000"><font color="#ffffff">0</font></td>
									<td width="33%" bgColor="#c0c0c0">0</td>
									<td width="34%" bgColor="#c0c0c0">1</td>
								</tr>
								<tr>
									<td width="33%" bgColor="#000000"><font color="#ffffff">1</font></td>
									<td width="33%" bgColor="#c0c0c0">1</td>
									<td width="34%" bgColor="#c0c0c0">1</td>
								</tr>
							</tbody>
						</table>
					</td>
					<td width="10%"></td>
					<td width="20%">
						<table width="100%" border="0">
							<tbody>
								<tr>
									<td width="33%"></td>
									<td width="33%" bgColor="#000000"><font color="#ffffff">0</font></td>
									<td width="34%" bgColor="#000000"><font color="#ffffff">1</font></td>
								</tr>
								<tr>
									<td width="33%" bgColor="#000000"><font color="#ffffff">0</font></td>
									<td width="33%" bgColor="#c0c0c0">0</td>
									<td width="34%" bgColor="#c0c0c0">1</td>
								</tr>
								<tr>
									<td width="33%" bgColor="#000000"><font color="#ffffff">1</font></td>
									<td width="33%" bgColor="#c0c0c0">1</td>
									<td width="34%" bgColor="#c0c0c0">0</td>
								</tr>
							</tbody>
						</table>
					</td>
				</tr>
			</tbody>
		</table>
		<p>These results can be summarized in English as:</p>
		<ul>
			<li>
			The result of a logical AND is true (1) if and only if both inputs are true,
			otherwise it is false (0).
			<li>
			The result of a logical OR is true (1) if either of the inputs its true,
			otherwise it is false (0).
			<li>
				The result of an exclusive OR is true (1) if and only if one input is true and
				the other is false, otherwise it is false (0).</li>
		</ul>
		<p>The tables show result of applying these operations on two one-bit values but as
			the 6502 comprises of eight bit registers and memory each instruction will
			operate on two eight bit values simultaneously as shown below.</p>
		<table border="0" width="100%">
			<tr>
				<td width="16%"></td>
				<td width="17%"><b><i>Logical AND (AND)</i></b></td>
				<td width="5%"></td>
				<td width="17%"><b><i>Logical OR (ORA)</i></b></td>
				<td width="5%"></td>
				<td width="17%"><b><i>Exclusive OR (EOR)</i></b></td>
			</tr>
			<tr>
				<td width="16%"><b><i>Value 1</i></b></td>
				<td width="17%">
					<table border="0" width="100%">
						<tr>
							<td width="12%" bgcolor="#000000"><font color="#ffffff">0</font></td>
							<td width="12%" bgcolor="#000000"><font color="#ffffff">0</font></td>
							<td width="12%" bgcolor="#000000"><font color="#ffffff">1</font></td>
							<td width="12%" bgcolor="#000000"><font color="#ffffff">1</font></td>
							<td width="13%" bgcolor="#000000"><font color="#ffffff">0</font></td>
							<td width="13%" bgcolor="#000000"><font color="#ffffff">0</font></td>
							<td width="13%" bgcolor="#000000"><font color="#ffffff">1</font></td>
							<td width="13%" bgcolor="#000000"><font color="#ffffff">1</font></td>
						</tr>
					</table>
				</td>
				<td width="5%"></td>
				<td width="17%">
					<table border="0" width="100%">
						<tr>
							<td width="12%" bgcolor="#000000"><font color="#ffffff">0</font></td>
							<td width="12%" bgcolor="#000000"><font color="#ffffff">0</font></td>
							<td width="12%" bgcolor="#000000"><font color="#ffffff">1</font></td>
							<td width="12%" bgcolor="#000000"><font color="#ffffff">1</font></td>
							<td width="13%" bgcolor="#000000"><font color="#ffffff">0</font></td>
							<td width="13%" bgcolor="#000000"><font color="#ffffff">0</font></td>
							<td width="13%" bgcolor="#000000"><font color="#ffffff">1</font></td>
							<td width="13%" bgcolor="#000000"><font color="#ffffff">1</font></td>
						</tr>
					</table>
				</td>
				<td width="5%"></td>
				<td width="17%">
					<table border="0" width="100%">
						<tr>
							<td width="12%" bgcolor="#000000"><font color="#ffffff">0</font></td>
							<td width="12%" bgcolor="#000000"><font color="#ffffff">0</font></td>
							<td width="12%" bgcolor="#000000"><font color="#ffffff">1</font></td>
							<td width="12%" bgcolor="#000000"><font color="#ffffff">1</font></td>
							<td width="13%" bgcolor="#000000"><font color="#ffffff">0</font></td>
							<td width="13%" bgcolor="#000000"><font color="#ffffff">0</font></td>
							<td width="13%" bgcolor="#000000"><font color="#ffffff">1</font></td>
							<td width="13%" bgcolor="#000000"><font color="#ffffff">1</font></td>
						</tr>
					</table>
				</td>
			</tr>
			<tr>
				<td width="16%"><b><i>Value 2</i></b></td>
				<td width="17%">
					<table border="0" width="100%">
						<tr>
							<td width="12%" bgcolor="#000000"><font color="#ffffff">0</font></td>
							<td width="12%" bgcolor="#000000"><font color="#ffffff">1</font></td>
							<td width="12%" bgcolor="#000000"><font color="#ffffff">0</font></td>
							<td width="12%" bgcolor="#000000"><font color="#ffffff">1</font></td>
							<td width="13%" bgcolor="#000000"><font color="#ffffff">0</font></td>
							<td width="13%" bgcolor="#000000"><font color="#ffffff">1</font></td>
							<td width="13%" bgcolor="#000000"><font color="#ffffff">0</font></td>
							<td width="13%" bgcolor="#000000"><font color="#ffffff">1</font></td>
						</tr>
					</table>
				</td>
				<td width="5%"></td>
				<td width="17%">
					<table border="0" width="100%">
						<tr>
							<td width="12%" bgcolor="#000000"><font color="#ffffff">0</font></td>
							<td width="12%" bgcolor="#000000"><font color="#ffffff">1</font></td>
							<td width="12%" bgcolor="#000000"><font color="#ffffff">0</font></td>
							<td width="12%" bgcolor="#000000"><font color="#ffffff">1</font></td>
							<td width="13%" bgcolor="#000000"><font color="#ffffff">0</font></td>
							<td width="13%" bgcolor="#000000"><font color="#ffffff">1</font></td>
							<td width="13%" bgcolor="#000000"><font color="#ffffff">0</font></td>
							<td width="13%" bgcolor="#000000"><font color="#ffffff">1</font></td>
						</tr>
					</table>
				</td>
				<td width="5%"></td>
				<td width="17%">
					<table border="0" width="100%">
						<tr>
							<td width="12%" bgcolor="#000000"><font color="#ffffff">0</font></td>
							<td width="12%" bgcolor="#000000"><font color="#ffffff">1</font></td>
							<td width="12%" bgcolor="#000000"><font color="#ffffff">0</font></td>
							<td width="12%" bgcolor="#000000"><font color="#ffffff">1</font></td>
							<td width="13%" bgcolor="#000000"><font color="#ffffff">0</font></td>
							<td width="13%" bgcolor="#000000"><font color="#ffffff">1</font></td>
							<td width="13%" bgcolor="#000000"><font color="#ffffff">0</font></td>
							<td width="13%" bgcolor="#000000"><font color="#ffffff">1</font></td>
						</tr>
					</table>
				</td>
			</tr>
			<tr>
				<td width="16%"><b><i>Result</i></b></td>
				<td width="17%">
					<table border="0" width="100%">
						<tr>
							<td width="12%" bgcolor="#c0c0c0">0</td>
							<td width="12%" bgcolor="#c0c0c0">0</td>
							<td width="12%" bgcolor="#c0c0c0">0</td>
							<td width="12%" bgcolor="#c0c0c0">1</td>
							<td width="13%" bgcolor="#c0c0c0">0</td>
							<td width="13%" bgcolor="#c0c0c0">0</td>
							<td width="13%" bgcolor="#c0c0c0">0</td>
							<td width="13%" bgcolor="#c0c0c0">1</td>
						</tr>
					</table>
				</td>
				<td width="5%"></td>
				<td width="17%">
					<table border="0" width="100%">
						<tr>
							<td width="12%" bgcolor="#c0c0c0">0</td>
							<td width="12%" bgcolor="#c0c0c0">1</td>
							<td width="12%" bgcolor="#c0c0c0">1</td>
							<td width="12%" bgcolor="#c0c0c0">1</td>
							<td width="13%" bgcolor="#c0c0c0">0</td>
							<td width="13%" bgcolor="#c0c0c0">1</td>
							<td width="13%" bgcolor="#c0c0c0">1</td>
							<td width="13%" bgcolor="#c0c0c0">1</td>
						</tr>
					</table>
				</td>
				<td width="5%"></td>
				<td width="17%">
					<table border="0" width="100%">
						<tr>
							<td width="12%" bgcolor="#c0c0c0">0</td>
							<td width="12%" bgcolor="#c0c0c0">1</td>
							<td width="12%" bgcolor="#c0c0c0">1</td>
							<td width="12%" bgcolor="#c0c0c0">0</td>
							<td width="13%" bgcolor="#c0c0c0">0</td>
							<td width="13%" bgcolor="#c0c0c0">1</td>
							<td width="13%" bgcolor="#c0c0c0">1</td>
							<td width="13%" bgcolor="#c0c0c0">0</td>
						</tr>
					</table>
				</td>
			</tr>
		</table>
		<p>It is important to understand the properties and practical applications of each
			of these operations as they are extensively used in other algorithms.</p>
		<ul>
			<li>
			Logical AND operates as a filter and is often used to select a subset of bits
			from a value (e.g. the status flags from a peripheral control chip).
			<li>
			Logical OR allows bits to be inserted into an existing value (e.g. to set
			control flags in a peripheral control chip).
			<li>
				Exclusive OR allows selected bits to be set or inverted.</li>
		</ul>
		<p>In the 6502 these operations are implemented by the <A href="reference.html#AND">AND</A>,
			<A href="reference.html#ORA">ORA</A> and <A href="reference.html#EOR">EOR</A> instructions.
			One of the values to be operated on will be the current contents of the
			accumulator, the other is in memory either as an immediate value or at a
			specified location. The result of the operation is placed in the accumulator
			and the zero and negative flags are set accordingly.</p>
		<pre>; Example logical operations
        AND #$0F        ;Filter out all but the least 4 bits
        ORA BITS,X      ;Insert some bits from a table
        EOR (DATA),Y    ;EOR against some data</pre>
		<p>A very common use of the EOR instruction is to calculate the 'complement' (or
			logical NOT) of a value. This involves inverting every bit in the value and is
			most easily calculated by exclusively ORing against an all ones value.</p>
		<pre>; Calculate the complement
        EOR #$FF</pre>
		<p>The macro library contains reference code for 16 and 32 bit AND, ORA, EOR and
			NOT operations although there is very little use for them outside of
			interpreters.</p>
		<h3>Shifts &amp; Rotates</h3>
		<p>The shift and rotate instructions allow the bits within&nbsp;either the
			accumulator or a memory location to be moved by one place either up (left) or
			down (right). When the bits are moved a new value will be needed to fill the
			vacant position created at one end of the value, and similarly the bit
			displaced at the opposite end will need to be caught and stored.</p>
		<P>Both shifts and rotates catch the displaced bit in the carry flag but they
			differ in how they fill the vacant position; shifts will always fill the vacant
			bit with a zero whilst a rotate will fill it with the value of the carry flag
			as it was at the start of the instruction.</P>
		<P>For example the following diagram shows the result of applying an 'Arithmetic
			Shift&nbsp;Left' (<A href="reference.html#ASL">ASL</A>) to the value $4D to
			give $9A.</P>
		<PRE>               +---+---+---+---+---+---+---+---+
Initial:       | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 |
               +---+---+---+---+---+---+---+---+
                 |   |   |   |   |   |   |   |
                /   /   /   /   /   /   /   /
               /   /   /   /   /   /   /   /    0
              /   /   /   /   /   /   /   /   /
             /   |   |   |   |   |   |   |   |
            /    v   v   v   v   v   v   v   v
               +---+---+---+---+---+---+---+---+
Result:   C=0&nbsp; |&nbsp;1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 |
               +---+---+---+---+---+---+---+---+</PRE>
		<P>Whist the following shows the result of applying a 'Rotate Left' (<A href="reference.html#ROL">ROL</A>)
			to the same value, but assuming that the carry contained the value one.</P>
		<PRE>               +---+---+---+---+---+---+---+---+
Initial:       | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | C=1
               +---+---+---+---+---+---+---+---+
                 |   |   |   |   |   |   |   |   /
                /   /   /   /   /   /   /   /   /
               /   /   /   /   /   /   /   /   /
              /   /   /   /   /   /   /   /   /
             /   |   |   |   |   |   |   |   |
            /    v   v   v   v   v   v   v   v
               +---+---+---+---+---+---+---+---+
Result:   C=0&nbsp; |&nbsp;1 | 0 | 0 | 1 | 1 | 0 | 1 | 1 |
               +---+---+---+---+---+---+---+---+</PRE>
		<P>Shifting the bits within a value (and introducing a zero as the least
			significant bit) has the effect of multiplying its value by two. In order to
			apply this multiplication to a value larger than a single byte we use ASL
			to&nbsp;shift the first byte and then ROL all the subsequent bytes as
			necessary using the carry flag to temporarily hold the displaced bits as they
			are moved from one byte to the next.</P>
		<PRE>; Shift a 16bit value by one place left (e.g. multiply by two)
_ASL16  ASL MEM+0       ;Shift the LSB
        ROL MEM+1       ;Rotate the MSB</PRE>
		<P>The behavior of the right shift as rotates follows the same pattern. For
			example we can apply a 'Logical Shift Right' (<A href="reference.html#LSR">LSR</A>
			)&nbsp;to the value $4D to give $26.<PRE>               +---+---+---+---+---+---+---+---+
Initial:       | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 |
               +---+---+---+---+---+---+---+---+
                 |   |   |   |   |   |   |   |
                  \   \   \   \   \   \   \   \
              0    \   \   \   \   \   \   \   \
                \   \   \   \   \   \   \   \   \
                 |   |   |   |   |   |   |   |   \
                 v   v   v   v   v   v   v   v    \
               +---+---+---+---+---+---+---+---+
Result:      &nbsp; |&nbsp;0 | 0 | 1 | 0 | 0 | 1 | 1 | 0 |  C=1
               +---+---+---+---+---+---+---+---+</PRE>
		<P>Or a 'Rotate Right' (<A href="reference.html#ROR">ROR</A>)&nbsp;of the same
			value, but assuming that the carry contained the value one to give $A6.</P>
		<PRE>               +---+---+---+---+---+---+---+---+
Initial:   C=1 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 |
               +---+---+---+---+---+---+---+---+
             \   |   |   |   |   |   |   |   |
              \   \   \   \   \   \   \   \   \
               \   \   \   \   \   \   \   \   \
                \   \   \   \   \   \   \   \   \
                 |   |   |   |   |   |   |   |   \
                 v   v   v   v   v   v   v   v    \
               +---+---+---+---+---+---+---+---+
Result:      &nbsp; |&nbsp;1 | 0 | 1 | 0 | 0 | 1 | 1 | 0 |  C=1
               +---+---+---+---+---+---+---+---+</PRE>
		<P>Not surprisingly if left shifts multiply a value by two then right shifts do an
			unsigned division by two. Again if we are applying the division to&nbsp;a
			multi-byte value we will typically use LSR on the first byte (the MSB this
			time) and ROR on all subsequent bytes.</P>
		<pre>; Shift a 16 bit value by one place right (e.g. divide by two)
_LSR16  LSR MEM+1       ;Shift the MSB
        ROR MEM+0       ;Rotate the LSB</pre>
		<p>There are a number of applications for shifts and rotates, not least the coding
			of generic multiply and divide algorithms which are discussed later.</p>
		<P>As was pointed out earlier right shifting a value two divide it by two only
			works on unsigned values. This is because the LSR is will always place a zero
			in the most significant bit of the MSB.&nbsp;To make this
			algorithm&nbsp;work&nbsp;for all two complement coded values we need
			to&nbsp;ensure that&nbsp;value of this bit is copied&nbsp;back into itself to
			keep the value the same sign.&nbsp;We can use another shift to achieve
        this.</P>
		<PRE>; Divide a signed 16 bit value by two
_DIV2   LDA MEM+1       ;Load the MSB
        ASL A           ;Copy the sign bit into C
        ROR MEM+1       ;And back into the MSB
        ROR MEM+0       ;Rotate the LSB as normal</PRE>
		<H3>Addition &amp; Subtraction</H3>
		<P>The 6502 processor provides 8 bit addition and subtraction instructions and a
			carry/borrow flag that is used to propagate the carry bit between operations.</P>
		<P>To implement a 16 bit addition the programmer must code two pairs of additions;
			one for the least significant bytes and one for the most significant bytes. The
			carry flag must be cleared before the first addition to ensure that an
			additional increment isn't performed.</P>
		<PRE>; 16 bit Binary Addition
        CLC             ;Ensure carry is clear
        LDA VLA+0       ;Add the two least significant bytes
        ADC VLB+0
        STA RES+0       ;... and store the result
        LDA VLA+1       ;Add the two most significant bytes
        ADC VLB+1       ;... and any propagated carry bit
        STA RES+1       ;... and store the result</PRE>
		<P>Subtraction follows the same pattern but the carry must be set before the first
			pair of bytes are subtracted to get the correct result.</P>
		<PRE>; 16 bit Binary Subtraction
        SEC             ;Ensure carry is set
        LDA VLA+0       ;Subtract the two least significant bytes
        SBC VLB+0
        STA RES+0       ;... and store the result
        LDA VLA+1       ;Subtract the two most significant bytes
        SBC VLB+1       ;... and any propagated borrow bit
        STA RES+1       ;... and store the result</PRE>
		<P>Both the addition and subtraction algorithm can be extended to 32 bits by
			repeating the LDA/ADC/STA or LDA/SBC/STA pattern for two further bytes worth of
			data.</P>
		<H3>Negation</H3>
		<P>The traditional approach to negating a twos complement number is to reverse all
			the bits (by EORing with $FF) and add one as shown below.</P>
		<PRE>; 8 bit Binary Negation
        CLC 		;Ensure carry is clear
	EOR #$FF	;Invert all the bits
	ADC #1		;... and add one</PRE>
		<P>This technique works well with a
			single byte already held in the accumulator but not with bigger numbers. With
			these it is easier just to subtract them from zero.</P>
		<PRE>; 16 bit Binary Negation
        SEC             ;Ensure carry is set
        LDA #0          ;Load constant zero
        SBC SRC+0       ;... subtract the least significant byte
        STA DST+0       ;... and store the result
        LDA #0          ;Load constant zero again
        SBC SRC+1       ;... subtract the most significant byte
        STA DST+1       ;... and store the result</PRE>
		<H3>Decimal Arithmetic</H3>
		<P>The behavior of the ADC and SBC instructions can be modified by setting or
			clearing the decimal mode flag in the processor status register. Normally
			decimal mode is disabled and ADC/SBC perform simple binary arithmetic (e.g. $99
			+ $01 =&gt; $9A Carry = 0), but if the flag is set with a SED instruction the
			processor will perform binary coded decimal arithmetic instead (e.g. $99 + $01
			=&gt; $00 Carry = 1).</P>
		<P>To make the 16 bit addition/subtraction code work in decimal mode simply include
			an SED at the start and a CLD at the end (to restore the processor to normal).</P>
		<PRE>; 16 bit Binary Code Decimal Addition
        SED             ;Set decimal mode flag
        CLC             ;Ensure carry is clear
        LDA VLA+0       ;Add the two least significant bytes
        ADC VLB+0
        STA RES+0       ;... and store the result
        LDA VLA+1       ;Add the two most significant bytes
        ADC VLB+1       ;... and any propagated carry bit
        STA RES+1       ;... and store the result
        CLD             ;Clear decimal mode</PRE>
		<P>Binary coded values are more easily converted to displayable digits and are
			useful for holding numbers such as high scores.</P>
		<PRE>; Print the BCD value in A as two ASCII digits
        PHA             ;Save the BCD value
        LSR A           ;Shift the four most significant bits
        LSR A           ;... into the four least significant
        LSR A
        LSR A
        ORA #'0'        ;Make an ASCII digit
        JSR PRINT       ;... and print it
        PLA             ;Recover the BCD value
        AND #$0F        ;Mask out all but the bottom 4 bits
        ORA #'0'        ;Make an ASCII digit
        JSR PRINT       ;... and print it</PRE>
<P>Another use for BCD is in the conversion of binary values to decimal ones.
Some algorithms perform this conversion by counting the number of times that
10000's, 1000's, 100's, 10's and 1's can be subtracted from the binary value before
it underflows, but I normally use a simple fixed loop that shifts the bits out
of the binary value one at a time&nbsp;and adds it&nbsp;to an
intermediate&nbsp;result that is being doubled (in BCD) on each iteration.</P><PRE>; Convert an 16 bit binary value into a 24bit BCD value
BIN2BCD LDA #0          ;Clear the result area
        STA RES+0
        STA RES+1
        STA RES+2
        LDX #16         ;Setup the bit counter
        SED             ;Enter decimal mode
_LOOP   ASL VAL+0       ;Shift a bit out of the binary
        ROL VAL+1       ;... value
        LDA RES+0       ;And add it into the result, doubling
        ADC RES+0       ;... it at the same time
        STA RES+0
        LDA RES+1
        ADC RES+1
        STA RES+1
        LDA RES+2
        ADC RES+2
        STA RES+2
        DEX             ;More bits to process?
        BNE _LOOP
        CLD             ;Leave decimal mode</PRE>
<P>One final odd use of decimal arithmetic&nbsp;is the conversion of hexadecimal
digits to printable ASCII characters. The usual&nbsp;way to perform&nbsp;this
conversion is to add $30 to the digit ($00 - $0F)&nbsp;to make an intermediate
result which is then&nbsp;examined to see if it&nbsp;is greater than or equal to
$3A. If it is then an additional $06 is added to make the result fall in the
range $41 - $46&nbsp;(e.g. 'A' - 'F').</P><PRE>; Convert a hex digit ($00-$0F) to ASCII ('0'-'9' or 'A'-'F')
HEX2ASC ORA #$30        ;Form the basic character code
        CMP #$3A        ;Does the result need adjustment?
        BCC .+4
        ADC #$05        ;Add 6 (5 and the carry) if needed</PRE>
<P>It turns out that in&nbsp;decimal mode the processor&nbsp;does&nbsp;basically
the same correction after an addition&nbsp;and with the&nbsp;right arguments we
can convert the digit to its ASCII character without performing any comparisons
as shown in the following code.</P><PRE>; Convert a hex digit ($00-$0F) to ASCII ('0'-'9' or 'A'-'F')
HEX2ASC SED             ;Enter BCD mode
        CLC             ;Ensure the carry is clear
        ADC #$90        ;Produce $90-$99 (C=0) or $00-$05 (C=1)
        ADC #$40        ;Produce $30-$39 or $41-$46
        CLD             ;Leave BCD mode</PRE>
<H3>Increments &amp; Decrements</H3>
		<P>Assembly programs frequently use memory based counters that occasionally need
			incrementing or decrementing by one. One way to achieve this would be to load
			the LSB and MSB in turn and add or subtract one with the <A href="reference.html#ADC">
				ADC</A>/<A href="reference.html#SBC">SBC</A> instructions, but the 6502 has
			a more efficient way to do this using <A href="reference.html#INC">INC</A> and <A href="reference.html#DEC">
				DEC</A>.</P>
		<P>Incrementing is straight forward, we just increment the least significant byte
			until the result becomes zero. This indicates that the calculation has wrapped
			round (e.g. $FF + $01 =&gt; $00) and an increment to the most significant byte
			is needed.</P>
		<PRE>; Increment a 16 bit value by one
_INC16  INC MEM+0       ;Increment the LSB
        BNE _DONE       ;If the result was not zero we're done
        INC MEM+1       ;Increment the MSB if LSB wrapped round
_DONE   EQU *</PRE>
		<P>Decrementing is a little trickier because we need to know when the least
			significant byte is about to underflow from $00 to $FF. The answer is to test
			it first by loading it into the accumulator to set the processor flags.</P>
		<PRE>; Decrement a 16 bit value by one
_DEC16  LDA MEM+0       ;Test if the LSB is zero
        BNE _SKIP       ;If it isn't we can skip the next instruction
        DEC MEM+1       ;Decrement the MSB when the LSB will underflow
_SKIP   DEC MEM+0       ;Decrement the LSB</PRE>
		<H3>Complex Memory Transfers</H3>
        <p>Moving data from one place to another is a common operation. If the
        amount of data to moved is 256 bytes or less and the source and target
        locations of the data are fixed then a simple loop around an indexed LDA
        followed by an indexed STA is the most efficient. Note that whilst both
        the X and Y registers can be used in indexed addressing modes&nbsp; an asymmetry
        in the 6502's instruction means that X is the better register to use if
        one or both of the memory areas resides on zero page.</p>
        <pre>; Move 256 bytes or less in a forward direction
	LDX #0		;Start with the first byte
_LOOP	LDA SRC,X	;Move it
	STA DST,X
	INX		;Then bump the index ...
	CPX #LEN	;... until we reach the limit
	BNE _LOOP</pre>
        <p>The corresponding code moving the last byte first is as follows:</p>
        <pre>; Move 256 bytes or less in a reverse direction
	LDX #LEN	;Start with the last byte
_LOOP	DEX		;Bump the index
	LDA SRC,X	;Move a byte
	STA DST,X
	CPX #0		;... until all bytes have moved
	BNE _LOOP</pre>
        <p>If the amount is even smaller (128 bytes or less) then we can
        eliminate the comparison against the limit and use the settings of the
        flags after a DEX to determine if the loop has finished.</p>
        <pre>; Move 128 bytes or less in a reverse direction
	LDX #LEN-1	;Start with the last byte
_LOOP	LDA SRC,X	;Move it
	STA DST,X
	DEX		;Then bump the index ...
	BPL _LOOP	;... until all bytes have moved</pre>
        <p>To create a completely generic memory transfer we must change to
        using indirect indexed addressing to access memory and use all the
        registers. The following code shows a forward transferring algorithm
        which first moves complete pages of 256 bytes followed by any remaining
        fragments of smaller size.</p>
		<pre>_MOVFWD	LDY #0		;Initialise the index
	LDX LEN+1	;Load the page count
	BEQ _FRAG	;... Do we only have a fragment?
_PAGE 	LDA (SRC),Y	;Move a byte in a page transfer
	STA (DST),Y
	INY		;And repeat for the rest of the
	BNE _PAGE	;... page
	INC SRC+1	;Then bump the src and dst addresses
	INC DST+1	;... by a page
	DEX		;And repeat while there are more
	BNE _PAGE	;... pages to move
_FRAG	CPY LEN+0	;Then while the index has not reached
	BEQ _DONE	;... the limit
	LDA (SRC),Y	;Move a fragment byte
	STA (DST),Y
	INY		;Bump the index and repeat
	BNE _FRAG\?
_DONE 	EQU *		;All done</pre>
		<p>&nbsp;</p>
		<H3>Character Classification</H3>
        <p>The standard C library provides a set of functions for classifying
        (e.g. is letter, is digit, is ASCII, is upper case, etc.) and modifying
        (e.g. to upper case and to lower case) characters defined in a header
        called &lt;ctype.h&gt;. This section describes how a similar set of
        functions can be coded in 6502 assembler. There are two techniques that
        can be applied to solve this problem, namely, comparisons or look up
        tables.</p>
        <dl>
          <dd><i>Note: These functions will be restricted to just the normal
            ASCII character range $00-$7F.</i></dd>
        </dl>
        <p>The look up table required to implement character
        classification&nbsp; needs a byte per character. Bits within the look up
        table indicate how the character is to be classified (e.g. control
        character, printable character, white space, decimal digit, hexadecimal
        digit, punctuation, upper case latter or lower case letter). To test a
        character for a specific classification you load its description byte
        from the table and test for the presence of certain bits (e.g. with
        AND).</p>
        <pre>; Constants describing the role of each classification bit
_CTL	EQU $80
_PRN	EQU $40
_WSP	EQU $20
_PCT	EQU $10
_UPR	EQU $08
_LWR	EQU $04
_DGT	EQU $02
_HEX	EQU $01

; Test if the character in A is a control character
ISCNTRL	TAX
	LDA #_CTL
	BNE TEST

; Test if the character in A is printable
ISPRINT	TAX
	LDA #_PRN
	BNE TEST

; Test if the character in A is punctation
ISPUNCT	TAX
	LDA #_PCT
	BNE TEST

; Test if the character in A is upper case
ISUPPER	TAX
	LDA #_UPR
	BNE TEST

; Test if the character in A is lower case
ISLOWER	TAX
	LDA #_LWR
	BNE TEST

; Test if the character in A is a letter
ISALPHA	TAX
	LDA #_UPR|_LWR
	BNE TEST

; Test if the character in A is a decimal digit
ISDIGIT	TAX
	LDA #_DGT
	BNE TEST

; Test if the character in A is a hexadecimal digit
ISXDIGIT TAX
	LDA #_HEX
	BNE TEST

; Test if the character in A is letter or a digit
ISALNUM	TAX
	LDA #_DGT|_UPR|_LWR

; Tests for the required bits in the look up table value
TEST	AND CTYPE,X
	BEQ FAIL

; Set the carry flag if any target bits were found
PASS	TXA
	SEC
	RTS

; Test if the character in A is in the ASCII range $00-$7F
ISASCII	TAX
	BPL PASS

; Clear the carry flag if no target bits were found
FAIL	TXA
	CLC
	RTS

; If A contains a lower case letter convert it to upper case
TOUPPER	JSR ISLOWER
	BCC *+4
	AND #$DF
	RTS

; If A contains an upper case letter convert it to lower case
TOLOWER	JSR ISUPPER
	BCC *+4
	ORA #$20
	RTS

; The lookup table of character descriptions
CTYPE	DB  _CTL		; NUL
	DB  _CTL		; SOH
	DB  _CTL		; STX
	DB  _CTL		; ETX
	DB  _CTL		; EOT
	DB  _CTL		; ENQ
	DB  _CTL		; ACK
	DB  _CTL		; BEL
	DB  _CTL		; BS
	DB  _CTL|_WSP		; TAB
	DB  _CTL|_WSP		; LF
	DB  _CTL|_WSP		; VT
	DB  _CTL|_WSP		; FF
	DB  _CTL|_WSP		; CR
	DB  _CTL		; SO
	DB  _CTL		; SI
	DB  _CTL		; DLE
	DB  _CTL		; DC1
	DB  _CTL		; DC2
	DB  _CTL		; DC3
	DB  _CTL		; DC4
	DB  _CTL		; NAK
	DB  _CTL		; SYN
	DB  _CTL		; ETB
	DB  _CTL		; CAN
	DB  _CTL		; EM
	DB  _CTL		; SUB
	DB  _CTL		; ESC
	DB  _CTL		; FS
	DB  _CTL		; GS
	DB  _CTL		; RS
	DB  _CTL		; US
	DB  _PRN|_WSP		; SPACE
	DB  _PRN|_PCT		; !
	DB  _PRN|_PCT		; &quot;
	DB  _PRN|_PCT		; #
	DB  _PRN|_PCT		; $
	DB  _PRN|_PCT		; %
	DB  _PRN|_PCT		; &amp;
	DB  _PRN|_PCT		; '
	DB  _PRN|_PCT		; (
	DB  _PRN|_PCT		; )
	DB  _PRN|_PCT		; *
	DB  _PRN|_PCT		; +
	DB  _PRN|_PCT		; ,
	DB  _PRN|_PCT		; -
	DB  _PRN|_PCT		; .
	DB  _PRN|_PCT		; /
	DB  _PRN|_DGT|_HEX	; 0
	DB  _PRN|_DGT|_HEX	; 1
	DB  _PRN|_DGT|_HEX	; 2
	DB  _PRN|_DGT|_HEX	; 3
	DB  _PRN|_DGT|_HEX	; 4
	DB  _PRN|_DGT|_HEX	; 5
	DB  _PRN|_DGT|_HEX	; 6
	DB  _PRN|_DGT|_HEX	; 7
	DB  _PRN|_DGT|_HEX	; 8
	DB  _PRN|_DGT|_HEX	; 9
	DB  _PRN|_PCT		; :
	DB  _PRN|_PCT		; ;
	DB  _PRN|_PCT		; &lt;
	DB  _PRN|_PCT		; =
	DB  _PRN|_PCT		; &gt;
	DB  _PRN|_PCT		; ?
	DB  _PRN|_PCT		; @
	DB  _PRN|_UPR|_HEX	; A
	DB  _PRN|_UPR|_HEX	; B
	DB  _PRN|_UPR|_HEX	; C
	DB  _PRN|_UPR|_HEX	; D
	DB  _PRN|_UPR|_HEX	; E
	DB  _PRN|_UPR|_HEX	; F
	DB  _PRN|_UPR		; G
	DB  _PRN|_UPR		; H
	DB  _PRN|_UPR		; I
	DB  _PRN|_UPR		; J
	DB  _PRN|_UPR		; K
	DB  _PRN|_UPR		; L
	DB  _PRN|_UPR		; M
	DB  _PRN|_UPR		; N
	DB  _PRN|_UPR		; O
	DB  _PRN|_UPR		; P
	DB  _PRN|_UPR		; Q
	DB  _PRN|_UPR		; R
	DB  _PRN|_UPR		; S
	DB  _PRN|_UPR		; T
	DB  _PRN|_UPR		; U
	DB  _PRN|_UPR		; V
	DB  _PRN|_UPR		; W
	DB  _PRN|_UPR		; X
	DB  _PRN|_UPR		; Y
	DB  _PRN|_UPR		; Z
	DB  _PRN|_PCT		; [
	DB  _PRN|_PCT		; \
	DB  _PRN|_PCT		; ]
	DB  _PRN|_PCT		; ^
	DB  _PRN|_PCT		; _
	DB  _PRN|_PCT		; `
	DB  _PRN|_LWR|_HEX	; a
	DB  _PRN|_LWR|_HEX	; b
	DB  _PRN|_LWR|_HEX	; c
	DB  _PRN|_LWR|_HEX	; d
	DB  _PRN|_LWR|_HEX	; e
	DB  _PRN|_LWR|_HEX	; f
	DB  _PRN|_LWR		; g
	DB  _PRN|_LWR		; h
	DB  _PRN|_LWR		; i
	DB  _PRN|_LWR		; j
	DB  _PRN|_LWR		; k
	DB  _PRN|_LWR		; l
	DB  _PRN|_LWR		; m
	DB  _PRN|_LWR		; n
	DB  _PRN|_LWR		; o
	DB  _PRN|_LWR		; p
	DB  _PRN|_LWR		; q
	DB  _PRN|_LWR		; r
	DB  _PRN|_LWR		; s
	DB  _PRN|_LWR		; t
	DB  _PRN|_LWR		; u
	DB  _PRN|_LWR		; v
	DB  _PRN|_LWR		; w
	DB  _PRN|_LWR		; x
	DB  _PRN|_LWR		; y
	DB  _PRN|_LWR		; z
	DB  _PRN|_PCT		; {
	DB  _PRN|_PCT		; |
	DB  _PRN|_PCT		; }
	DB  _PRN|_PCT		; ~
	DB  _CTL		; DEL</pre>
        <p>If we use comparisons then each function will consist of a number of
        comparison stages to determine if a provided character has an
        appropriate value. In most cases these functions are quite small but one
        or two of them may involve many stages (e.g. is punctuation). The
        execution time will vary according to the number of the tests a
        character is subjected to.&nbsp;</p>
        <pre>ISUPPER	CMP #'A'
	BCC FAIL
	CMP #'Z'+1
	BCS FAIL
	; Drop thru here on success

ISLOWER	CMP #'a'
	BCC FAIL
	CMP #'z'+1
	BCS FAIL
	; Drop thru here on success

ISALPHA	CMP #'A'
	BCC FAIL
	CMP #'Z'+1
	BCC PASS
	CMP #'a'
	BCC FAIL
	CMP #'z'+1
	BCS FAIL
PASS	EQU *
	; Drop thru here on success</pre>
        <p>Which solution is best? As in so many cases it depends on your
        program. If you only need one or two tests and memory size is an issue
        then the comparison approach will generate less code but may be slightly
        slower (for the complex tests), otherwise the look up table is simple
        and fast.</p>
		<H3>Some notes on my macro library</H3>
		<P>As I said in the introduction to this section all of the algorithms presented
			here are taken from my macro library. Coding simple algorithms like these as
			macros has several advantages over subroutine libraries on the 6502 processor,
			namely:</P>
		<UL>
			<LI>
			The assembler adjusts them automatically to zero page or absolute addressing
			depending on the parameters.
			<LI>
			They can be used either inline (for speed) or expanded into subroutines (to
			save space) as needed.
			<LI>
			The same macro can be used several times but customized in each case to suit
			its use at that time.
			<LI>
				The macros can optimize the code they generate under some circumstances (e.g.
				_XFR16 detects when the source and target addresses are the same and does
				nothing).</LI>
		</UL>
		<P>Another feature of the macros is that they will generate code for the 65SC02
			processor using the additional instructions on that processor if the assembler
			defines the correct symbol. (This processor was used in the BBC Microcomputers
			6502 second processor that's why I decided to support it).</P>
		<P>The routines in the currently library are:</P>
		<P><TABLE WIDTH="100%" BORDER="1" CELLSPACING="0" CELLPADDING="0">
				<TR>
					<TD WIDTH="22%"><B>Macro Name</B></TD>
					<TD WIDTH="78%"><B>Description</B></TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_CLR16</TD>
					<TD WIDTH="78%">Clears 16 bits of memory to zero</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_CLR32</TD>
					<TD WIDTH="78%">Clears 32 bits of memory to zero</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_CLR32C</TD>
					<TD WIDTH="78%">Clears 32 bits of memory to zero iteratively</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_XFR16</TD>
					<TD WIDTH="78%">Moves 16 bits of memory</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_XFR32</TD>
					<TD WIDTH="78%">Moves 32 bits of memory</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_XFR32C</TD>
					<TD WIDTH="78%">Moves 32 bits of memory iteratively</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_SET16I</TD>
					<TD WIDTH="78%">Load a 16 bit constant into memory</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_NOT16</TD>
					<TD WIDTH="78%">Compute the NOT of a 16 bit value</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_NOT32</TD>
					<TD WIDTH="78%">Compute the NOT of a 32 bit value</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_NOT32C</TD>
					<TD WIDTH="78%">Compute the NOT of a 32 bit value iteratively</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_ORA16</TD>
					<TD WIDTH="78%">Compute the OR of two 16 bit values</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_ORA32</TD>
					<TD WIDTH="78%">Compute the OR of two 32 bit values&nbsp;</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_ORA32C</TD>
					<TD WIDTH="78%">Compute the OR of two 32 bit values iteratively</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_AND16</TD>
					<TD WIDTH="78%">Compute the AND of two 16 bit values</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_AND32</TD>
					<TD WIDTH="78%">Compute the AND of two 32 bit values</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_AND32C</TD>
					<TD WIDTH="78%">Compute the AND of two 32 bit values iteratively</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_EOR16</TD>
					<TD WIDTH="78%">Compute the EOR of two 16 bit values</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_EOR32</TD>
					<TD WIDTH="78%">Compute the EOR of two 32 bit values</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_EOR32C</TD>
					<TD WIDTH="78%">Compute the EOR of two 32 bit values iteratively</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_ASL16</TD>
					<TD WIDTH="78%">Compute the arithmetic left shift of a 16 bit value</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_ASL32</TD>
					<TD WIDTH="78%">Compute the arithmetic left shift of a 32 bit value</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_ROL16</TD>
					<TD WIDTH="78%">Compute the left rotation of a 16 bit value</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_ROL32</TD>
					<TD WIDTH="78%">Compute the left rotation of a 32 bit value</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_LSR16</TD>
					<TD WIDTH="78%">Compute the logical right shift of a 16 bit value</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_LSR32</TD>
					<TD WIDTH="78%">Compute the logical right shift of a 32 bit value</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_ROR16</TD>
					<TD WIDTH="78%">Compute the right rotation of a 16 bit value</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_ROR32</TD>
					<TD WIDTH="78%">Compute the right rotation of a 32 bit value</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_INC16</TD>
					<TD WIDTH="78%">Increment a 16 bit value</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_INC32</TD>
					<TD WIDTH="78%">Increment a 32 bit value</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_DEC16</TD>
					<TD WIDTH="78%">Decrement a 16 bit value</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_DEC32</TD>
					<TD WIDTH="78%">Decrement a 32 bit value</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_ADD16</TD>
					<TD WIDTH="78%">Add two 16 bit values</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_ADD32</TD>
					<TD WIDTH="78%">Add two 32 bit values</TD>
				</TR>
				<TR>
					<TD WIDTH="22%" HEIGHT="22">_SUB16&nbsp;</TD>
					<TD WIDTH="78%" HEIGHT="22">Subtract two 16 bit values</TD>
				</TR>
				<TR>
					<TD WIDTH="22%" HEIGHT="22">_SUB32</TD>
					<TD WIDTH="78%" HEIGHT="22">Subtract two 32 bit values</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_NEG16</TD>
					<TD WIDTH="78%">Negate a 16 bit value</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_NEG32</TD>
					<TD WIDTH="78%">Negate a 32 bit value</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_ABS16</TD>
					<TD WIDTH="78%">Compute the absolute value of a 16 bit value</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_ABS32</TD>
					<TD WIDTH="78%">Compute the absolute value of a 32 bit value</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_MUL16</TD>
					<TD WIDTH="78%">Calculate the 16 bit product of two 16 bit values</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_MUL16X</TD>
					<TD WIDTH="78%">Calculate the 32 bit product of two 16 bit values</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_MUL32</TD>
					<TD WIDTH="78%">Calculate the 32 bit product of two 32 bit values</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_MUL16I</TD>
					<TD WIDTH="78%">Generate the code for a 16 bit constant multiply</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_DIV16</TD>
					<TD WIDTH="78%">Calculate the 16 bit quotient &amp; remainder of a 16
						bit value and 16 bit dividend</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_DIV16X</TD>
					<TD WIDTH="78%">Calculate the 16 bit quotient &amp; remainder of a 32
						bit value and 16 bit dividend</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_DIV32</TD>
					<TD WIDTH="78%">Calculate the 32 bit quotient &amp; remainder of a 32
						bit value and 32 bit dividend</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_CMP16</TD>
					<TD WIDTH="78%">Compare two 16 bit values</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_CMP32</TD>
					<TD WIDTH="78%">Compare two 32 bit values</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_MEMFWD&nbsp;</TD>
					<TD WIDTH="78%">Move a block for memory a forward direction</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_MEMREV</TD>
					<TD WIDTH="78%">Not Implemented</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_MEMCPY</TD>
					<TD WIDTH="78%">Not Implemented</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_STRLEN</TD>
					<TD WIDTH="78%">Compute the length of a 'C' style string</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_STRCPY</TD>
					<TD WIDTH="78%">Copy a 'C' style string</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_STRCMP</TD>
					<TD WIDTH="78%">Compare two 'C' style strings</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">_STRNCMP</TD>
					<TD WIDTH="78%">Not implemented</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">&nbsp;</TD>
					<TD WIDTH="78%">&nbsp;</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">&nbsp;</TD>
					<TD WIDTH="78%">&nbsp;</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">&nbsp;</TD>
					<TD WIDTH="78%">&nbsp;</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">&nbsp;</TD>
					<TD WIDTH="78%">&nbsp;</TD>
				</TR>
				<TR>
					<TD WIDTH="22%">&nbsp;</TD>
					<TD WIDTH="78%">&nbsp;</TD>
				</TR>
			</TABLE>
		<P>Examine the code for more details on the macro parameters and usage.</P>
		<P><TABLE BORDER="0" CELLPADDING="0" CELLSPACING="0" WIDTH="100%" HEIGHT="30">
				<TR>
					<TD WIDTH="25%" BGCOLOR="#aaaaff">&nbsp;<A href="addressing.html">&lt;&lt; Back</A></TD>
					<TD WIDTH="25%" BGCOLOR="#aaaaff">
						<P><CENTER><A href="../index.html" target=_parent>Home</A></CENTER>
					</TD>
					<TD WIDTH="25%" BGCOLOR="#aaaaff">
						<P><CENTER><A href="index.html">Contents</A></CENTER>
					</TD>
					<TD ALIGN="right" WIDTH="25%" BGCOLOR="#aaaaff"><A href="reference.html">Next &gt;&gt;</A></TD>
				</TR>
			</TABLE>
		<P>
<HR>
<script type="text/javascript"><!--
google_ad_client = "pub-0826595092783671";
/* 6502 Footer */
google_ad_slot = "9966603696";
google_ad_width = 728;
google_ad_height = 90;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
<HR>
<script type="text/javascript"><!--
google_ad_client = "pub-0826595092783671";
/* 6502 Links */
google_ad_slot = "4173075094";
google_ad_width = 728;
google_ad_height = 15;
//-->
</script>
<script type="text/javascript"
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-9026746-2");
pageTracker._trackPageview();
} catch(err) {}</script>
<HR ALIGN="left">
		This page was last updated on 19th March 2004
	</BODY>
</HTML>
